import { Service } from 'egg';
import { Rights } from '../model/rights';
import { Role } from '../model/role';

/**
 * User Service
 */
export default class User extends Service {
  // 登录处理
  public async getUser({ username, email, phone, password }) {
    // 先把密码加密了再去查
    password = this.ctx.helper.encryptText(password);
    let res;
    // 如果用户输入的是邮箱账号,则执行邮箱的逻辑不判断下面的了
    if (email) {
      res = await this.findUser({ email, password });
      // 如果用户输入的是手机账号,则执行手机的逻辑不判断下面的了
    } else if (phone) {
      res = await this.findUser({ phone, password });
      // 最后在执行普通账号的
    } else if (username) {
      res = await this.findUser({ username, password });
    }
    try {
      // 过滤掉为null的值
      Object.keys(res.dataValues).forEach(key => {
        if (!res.dataValues[key]) delete res.dataValues[key];
      });
      delete res.dataValues.password;
      // 在 sequelize 中如果想要返回虚拟字段就不能返回dataValues
      return res;
    } catch (e) {
      throw new Error('用户名或密码不正确');
    }
  }
  public async createUser(obj) {
    const { username, email, phone, password } = obj;
    // 先把密码加密在存入数据库
    obj.password = this.ctx.helper.encryptText(password);
    if (username) {
      // 普通注册
      return await this.createUserByUserName(username, obj); // data.dataValues;
    } else if (email) {
      // 邮箱注册
      return await this.createUserByEmailName(email, obj); // data.dataValues;
    } else if (phone) {
      // 手机注册
      return await this.createUserByPhone(phone, obj);
    }
  }


  // 普通用户添加
  private async createUserByUserName(username, obj) {
    // 1.查询当前用户是否存在
    const user = await this.findUser({ username });
    if (user) {
      throw new Error('当前用户已存在');
    }
    // 如果不存在则保存到数据库中
    const data = await this.ctx.model.User.create(obj);
    // console.log(data.dataValues);
    // 返回存储信息给客户端
    const userData = data.dataValues;
    delete userData.password;
    return userData;
  }
  // 邮箱用户添加
  private async createUserByEmailName(email, obj) {
    // 1.查询当前用户是否存在
    const user = await this.findUser({ email });
    if (user) {
      throw new Error('当前用户已存在');
    }
    // 如果不存在则保存到数据库中
    const data = await this.ctx.model.User.create(obj);
    // console.log(data.dataValues);
    // 返回存储信息给客户端
    const userData = data.dataValues;
    delete userData.password;
    return userData;
  }
  // 手机用户添加
  private async createUserByPhone(phone, obj) {
    // 1.查询当前用户是否存在
    const user = await this.findUser({ phone });
    if (user) {
      throw new Error('当前用户已存在');
    }
    // 2.如果不存在才保存
    const data = await this.ctx.model.User.create(obj);
    const userData = data.dataValues;
    delete userData.password;
    return userData;
  }
  // 查询数据库中有没有当前用户
  private async findUser(options) {
    // 这里返回的数据大小过大, 所以生成jwt的时候取其中的登录账号作为对象值就行了
    const user:any = await this.ctx.model.User.findOne({
      where: options,
      // 找出user表中包含的roles表，roles表中的rights表
      include: [
        {
          model: Role,
          include: [
            { model: Rights },
          ],
        },
      ],
    });

    // 1.获取当前登录用户的所有权限
    let allRights: any[] = [];
    // 当前用户有哪些角色
    user.roles.forEach(role => {
      // 角色拥有哪些权限
      role.rights.forEach(item => {
        // 都追加到新的数组中
        allRights.push(item);
      });
    });
    // 2.剔除重复的项
    allRights = allRights.reduce((arr, item) => {
      const index = arr.findIndex(v => v.dataValues.id === item.dataValues.id);
      if (index === -1) {
        arr.push(item);
      }
      return arr;
    }, []);

    // const temp = {};
    // allRights = allRights.reduce((arr, item) => {
    //   if (!temp[item.dataValues.id]) {
    //     arr.push(item);
    //     temp[item.dataValues.id] = true;
    //   }
    //   return arr;
    // }, []);

    // 生成权限树
    // eslint-disable-next-line array-callback-return
    allRights = allRights.filter((outItem:any) => {
      allRights.forEach(inItem => {
        if (outItem.dataValues.id === inItem.dataValues.pid) {
          outItem.dataValues.children ? '' : outItem.dataValues.children = [];
          outItem.dataValues.children.push(inItem);
        }
      });
      if (outItem.dataValues.level === 0) return true;
    });
    user.dataValues.rightsTree = allRights;
    return user;
  }
}
